import pandas as pd
import os
from datetime import datetime
import numpy as np
import tkinter as tk
from tkinter import filedialog, messagebox


def select_source_file():
    """选择源文件"""
    root = tk.Tk()
    root.withdraw()  # 隐藏主窗口

    file_path = filedialog.askopenfilename(
        title="选择源Excel文件",
        filetypes=[("Excel files", "*.xlsx *.xls"), ("All files", "*.*")]
    )

    return file_path


def select_output_file():
    """选择输出文件路径和名称"""
    root = tk.Tk()
    root.withdraw()  # 隐藏主窗口

    file_path = filedialog.asksaveasfilename(
        title="保存汇总文件",
        defaultextension=".xlsx",
        filetypes=[("Excel files", "*.xlsx"), ("All files", "*.*")]
    )

    return file_path


def has_substantial_data(row, value_columns):
    """
    检查一行是否有实质内容

    Parameters:
    row: 数据行
    value_columns: 需要检查的列名列表

    Returns:
    bool: 如果有实质内容返回True，否则返回False
    """
    for col in value_columns:
        value = row[col]
        # 检查值是否为空、NaN、None或只有斜杠等无意义字符
        if pd.notna(value) and str(value).strip() not in ['', '/', ',/', ' ', 'NaN', 'None']:
            return True
    return False


def merge_instrument_records(source_file, output_file):
    """
    将多个工作表中的仪器使用记录合并到一个工作表中

    Parameters:
    source_file: 源Excel文件路径
    output_file: 输出Excel文件路径
    """

    # 读取源文件
    print(f"正在读取源文件: {source_file}")
    xl = pd.ExcelFile(source_file)

    # 存储所有工作表数据的列表
    all_data = []

    # 定义目标列名
    target_columns = ['分析日期', '任务单号', '检测项目', '使用人']
    value_columns = ['任务单号', '检测项目', '使用人']  # 用于检查实质内容的列

    # 遍历所有工作表
    for sheet_name in xl.sheet_names:
        print(f"处理工作表: {sheet_name}")

        # 读取工作表数据
        df = pd.read_excel(source_file, sheet_name=sheet_name)

        # 如果DataFrame为空或只有表头，跳过
        if df.empty or len(df) <= 1:
            print(f"  跳过空工作表: {sheet_name}")
            continue

        # 创建新DataFrame来存储处理后的数据
        processed_df = pd.DataFrame(columns=target_columns)

        # 映射列名
        column_mapping = {}

        # 查找匹配的列
        for target_col in target_columns:
            for actual_col in df.columns:
                # 检查列名是否包含目标列名的关键词
                if target_col in str(actual_col):
                    column_mapping[target_col] = actual_col
                    break

        # 如果找到了所有需要的列，则提取数据
        if len(column_mapping) == len(target_columns):
            for target_col in target_columns:
                if target_col in column_mapping:
                    processed_df[target_col] = df[column_mapping[target_col]]

            # 添加来源工作表信息
            processed_df['来源工作表'] = sheet_name

            # 过滤没有实质内容的行
            original_count = len(processed_df)
            processed_df = processed_df[processed_df.apply(
                lambda row: has_substantial_data(row, value_columns), axis=1
            )]
            filtered_count = len(processed_df)

            print(f"  原始行数: {original_count}, 过滤后行数: {filtered_count}")

            # 如果过滤后还有数据，则添加到总数据列表
            if not processed_df.empty:
                all_data.append(processed_df)
            else:
                print(f"  跳过无实质内容的工作表: {sheet_name}")
        else:
            print(f"  警告: 工作表 '{sheet_name}' 中缺少必要的列")
            print(f"  找到的列: {list(column_mapping.keys())}")

    # 合并所有数据
    if all_data:
        merged_df = pd.concat(all_data, ignore_index=True)

        # 数据清洗
        print("正在进行数据清洗...")

        # 处理日期格式
        def clean_date(date_val):
            if pd.isna(date_val):
                return date_val
            # 处理Excel序列号日期
            if isinstance(date_val, (int, float)):
                # 检查是否是合理的Excel日期序列号（通常在40000-50000之间）
                if 40000 <= date_val <= 50000:
                    try:
                        return (datetime(1899, 12, 30) + pd.Timedelta(days=date_val)).strftime('%Y-%m-%d %H:%M:%S')
                    except:
                        return date_val
            # 尝试解析日期字符串
            try:
                if isinstance(date_val, str):
                    return pd.to_datetime(date_val).strftime('%Y-%m-%d %H:%M:%S')
            except:
                pass
            return date_val

        merged_df['分析日期'] = merged_df['分析日期'].apply(clean_date)

        # 处理任务单号中的特殊字符
        def clean_task_number(task_num):
            if pd.isna(task_num):
                return task_num
            task_str = str(task_num).strip()
            # 替换常见的错误字符
            task_str = task_str.replace(',/', '/').replace(' ,/', '/').replace('，/', '/')
            # 去除多余的空格
            task_str = ' '.join(task_str.split())
            return task_str

        merged_df['任务单号'] = merged_df['任务单号'].apply(clean_task_number)

        # 清理检测项目列
        def clean_test_item(item):
            if pd.isna(item):
                return item
            item_str = str(item).strip()
            # 去除多余的空格
            item_str = ' '.join(item_str.split())
            return item_str

        merged_df['检测项目'] = merged_df['检测项目'].apply(clean_test_item)

        # 清理使用人列
        def clean_user(user):
            if pd.isna(user):
                return user
            user_str = str(user).strip()
            # 去除多余的空格
            user_str = ' '.join(user_str.split())
            return user_str

        merged_df['使用人'] = merged_df['使用人'].apply(clean_user)

        # 去重处理
        print("正在进行去重处理...")
        original_count = len(merged_df)

        # 基于四个关键列进行去重
        key_columns = ['分析日期', '任务单号', '检测项目', '使用人']
        merged_df = merged_df.drop_duplicates(subset=key_columns, keep='first')

        # 显示去重统计
        final_count = len(merged_df)
        print(f"去重统计:")
        print(f"  原始记录数: {original_count}")
        print(f"  去重后记录数: {final_count}")
        print(f"  移除重复记录: {original_count - final_count}")

        # 保存到新文件
        print(f"正在保存到: {output_file}")
        with pd.ExcelWriter(output_file, engine='openpyxl') as writer:
            # 保存汇总数据
            merged_df.to_excel(writer, sheet_name='汇总数据', index=False)

            # 添加去重统计信息
            stats_data = {
                '统计项目': ['原始记录数', '去重后记录数', '移除重复记录数'],
                '数量': [original_count, final_count, original_count - final_count]
            }
            stats_df = pd.DataFrame(stats_data)
            stats_df.to_excel(writer, sheet_name='去重统计', index=False)

            # 添加数据透视表 - 按使用人和工作表统计
            try:
                pivot_table1 = pd.pivot_table(merged_df,
                                              values='分析日期',
                                              index='使用人',
                                              columns='来源工作表',
                                              aggfunc='count',
                                              fill_value=0)
                pivot_table1.to_excel(writer, sheet_name='按使用人统计')
            except Exception as e:
                print(f"创建按使用人统计表时出错: {e}")

            # 添加数据透视表 - 按检测项目统计
            try:
                pivot_table2 = pd.pivot_table(merged_df,
                                              values='分析日期',
                                              index='检测项目',
                                              aggfunc='count')
                pivot_table2 = pivot_table2.sort_values('分析日期', ascending=False)
                pivot_table2.to_excel(writer, sheet_name='按检测项目统计')
            except Exception as e:
                print(f"创建按检测项目统计表时出错: {e}")

            # 添加月度使用统计
            try:
                # 提取月份信息
                merged_df['月份'] = pd.to_datetime(merged_df['分析日期']).dt.to_period('M')
                monthly_stats = merged_df.groupby(['月份', '来源工作表']).size().unstack(fill_value=0)
                monthly_stats.to_excel(writer, sheet_name='月度使用统计')
            except Exception as e:
                print(f"创建月度使用统计表时出错: {e}")

        print(f"汇总完成！共处理 {final_count} 条有效记录（去重后）")
        print(f"使用人统计:")
        print(merged_df['使用人'].value_counts())
        print(f"工作表来源统计:")
        print(merged_df['来源工作表'].value_counts())

        return True, f"汇总完成！共处理 {final_count} 条有效记录（去重后）"

    else:
        return False, "没有找到可合并的数据"


# 使用示例
if __name__ == "__main__":
    # 创建根窗口（隐藏）
    root = tk.Tk()
    root.withdraw()

    # 选择源文件
    print("请选择源Excel文件...")
    source_path = select_source_file()

    if not source_path:
        print("未选择源文件，程序退出。")
        exit()

    # 选择输出文件
    print("请选择保存位置和文件名...")
    output_path = select_output_file()

    if not output_path:
        print("未选择输出文件，程序退出。")
        exit()

    # 检查源文件是否存在
    if not os.path.exists(source_path):
        messagebox.showerror("错误", f"源文件不存在: {source_path}")
        print(f"错误: 源文件不存在 - {source_path}")
    else:
        try:
            success, message = merge_instrument_records(source_path, output_path)
            if success:
                messagebox.showinfo("完成", message)
                print("程序执行成功！")
            else:
                messagebox.showwarning("警告", message)
        except Exception as e:
            error_msg = f"执行过程中出现错误: {str(e)}"
            messagebox.showerror("错误", error_msg)
            print(error_msg)
            import traceback

            traceback.print_exc()

    # 关闭根窗口
    root.destroy()